<html>

<head>
	<title>P2P Demo</title>
	<style>
		body {
			overflow: hidden;
			margin: 0px;
			padding: 0px;
		}

		#local_view {
			width: 100%;
			height: 100%;
		}

		#remote_view {
			width: 9%;
			height: 16%;
			position: absolute;
			top: 10%;
			right: 10%;
		}

		#left {
			width: 10%;
			height: 5%;
			position: absolute;
			left: 10%;
			top: 10%;
		}

		#p_websocket_state,
		#input_server_url,
		.my_button {
			width: 100%;
			height: 100%;
			display: block;
			margin-bottom: 10%;
		}
	</style>
</head>

<body>
	<video id="local_view" autoplay controls muted></video>
	<video id="remote_view" autoplay controls muted></video>

	<div id="left">
		<p id="p_websocket_state">WebSocket 已断开</p>
		<input id="input_server_url" type="text" placeholder="请输入服务器地址" value="ws://192.168.1.104:8888"></input>
		<button id="btn_connect" class="my_button" onclick="connect()">连接 WebSocket</button>
		<button id="btn_disconnect" class="my_button" onclick="disconnect()">断开 WebSocket</button>
		<button id="btn_call" class="my_button" onclick="call()">呼叫</button>
		<button id="btn_hang_up" class="my_button" onclick="hangUp()">挂断</button>
	</div>
</body>

<script type="text/javascript">
	let localView = document.getElementById("local_view");
	let remoteView = document.getElementById("remote_view");
	var localStream;
	var peerConnection;

	function createPeerConnection() {
		let rtcPeerConnection = new RTCPeerConnection();
		rtcPeerConnection.oniceconnectionstatechange = function (event) {
			if ("disconnected" == event.target.iceConnectionState) {
				hangUp();
			}
		}
		rtcPeerConnection.onicecandidate = function (event) {
			console.log("onicecandidate--->" + event.candidate);
			let iceCandidate = event.candidate;
			if (iceCandidate == null) {
				return;
			}
			sendIceCandidate(iceCandidate);
		}
		rtcPeerConnection.ontrack = function (event) {
			console.log("remote ontrack--->" + event.streams);
			let streams = event.streams;
			if (streams && streams.length > 0) {
				remoteView.srcObject = streams[0];
			}
		}
		return rtcPeerConnection
	}

	function call() {
		// 创建 PeerConnection
		peerConnection = createPeerConnection();
		// 为 PeerConnection 添加音轨、视轨
		for (let i = 0; localStream != null && i < localStream.getTracks().length; i++) {
			const track = localStream.getTracks()[i];
			peerConnection.addTrack(track, localStream);
		}
		// 通过 PeerConnection 创建 offer，获取 sdp
		peerConnection.createOffer().then(function (sessionDescription) {
			console.log("create offer success.");
			// 将 offer sdp 作为参数 setLocalDescription
			peerConnection.setLocalDescription(sessionDescription).then(function () {
				console.log("set local sdp success.");
				// 发送 offer sdp
				sendOffer(sessionDescription)
			})
		})
	}

	function hangUp() {
		if (peerConnection != null) {
			peerConnection.close();
			peerConnection = null;
		}
		remoteView.removeAttribute('src');
		remoteView.load();
	}

	function sendOffer(offer) {
		var jsonObject = {
			"msgType": "sdp",
			"type": offer.type,
			"sdp": offer.sdp
		};
		send(JSON.stringify(jsonObject));
	}

	function receivedOffer(offer) {
		// 创建 PeerConnection
		peerConnection = createPeerConnection();
		// 为 PeerConnection 添加音轨、视轨
		for (let i = 0; localStream != null && i < localStream.getTracks().length; i++) {
			const track = localStream.getTracks()[i];
			peerConnection.addTrack(track, localStream);
		}
		// 将 offer sdp 作为参数 setRemoteDescription
		peerConnection.setRemoteDescription(offer).then(function () {
			console.log("set remote sdp success.");
			// 通过 PeerConnection 创建 answer，获取 sdp
			peerConnection.createAnswer().then(function (sessionDescription) {
				console.log("create answer success.");
				// 将 answer sdp 作为参数 setLocalDescription
				peerConnection.setLocalDescription(sessionDescription).then(function () {
					console.log("set local sdp success.");
					// 发送 answer sdp
					sendAnswer(sessionDescription);
				})
			})
		})
	}

	function sendAnswer(answer) {
		var jsonObject = {
			"msgType": "sdp",
			"type": answer.type,
			"sdp": answer.sdp
		};
		send(JSON.stringify(jsonObject));
	}

	function receivedAnswer(answer) {
		// 收到 answer sdp，将 answer sdp 作为参数 setRemoteDescription
		peerConnection.setRemoteDescription(answer).then(function () {
			console.log("set remote sdp success.");
		})
	}

	function sendIceCandidate(iceCandidate) {
		var jsonObject = {
			"msgType": "iceCandidate",
			"id": iceCandidate.sdpMid,
			"label": iceCandidate.sdpMLineIndex,
			"candidate": iceCandidate.candidate
		};
		send(JSON.stringify(jsonObject));
	}

	function receivedCandidate(iceCandidate) {
		peerConnection.addIceCandidate(iceCandidate);
	}

	navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(function (mediaStream) {
		// 初始化 PeerConnectionFactory
		// 创建 EglBase
		// 创建 PeerConnectionFactory
		// 创建音轨
		// 创建视轨
		localStream = mediaStream;
		// 初始化本地视频渲染控件
		// 初始化远端视频渲染控件
		// 开始本地渲染
		localView.srcObject = mediaStream;
	}).catch(function (error) {
		console.log("error--->" + error);
	})

</script>

<script type="text/javascript">
	var websocket;
	function connect() {
		let inputServerUrl = document.getElementById("input_server_url");
		let pWebsocketState = document.getElementById("p_websocket_state");
		let url = inputServerUrl.value;
		websocket = new WebSocket(url);
		websocket.onopen = function () {
			console.log("onOpen");
			pWebsocketState.innerText = "WebSocket 已连接";
		}
		websocket.onmessage = function (message) {
			console.log("onmessage--->" + message.data);
			let jsonObject = JSON.parse(message.data);
			let msgType = jsonObject["msgType"];
			if ("sdp" == msgType) {
				let type = jsonObject["type"];
				if ("offer" == type) {
					let options = {
						"type": jsonObject["type"],
						"sdp": jsonObject["sdp"]
					}
					let offer = new RTCSessionDescription(options);
					receivedOffer(offer);
				} else if ("answer" == type) {
					let options = {
						"type": jsonObject["type"],
						"sdp": jsonObject["sdp"]
					}
					let answer = new RTCSessionDescription(options);
					receivedAnswer(answer);
				}
			} else if ("iceCandidate" == msgType) {
				let options = {
					"sdpMLineIndex": jsonObject["label"],
					"sdpMid": jsonObject["id"],
					"candidate": jsonObject["candidate"]
				}
				let iceCandidate = new RTCIceCandidate(options);
				receivedCandidate(iceCandidate);
			}
		}
		websocket.onclose = function (error) {
			console.log("onclose--->" + error);
			pWebsocketState.innerText = "WebSocket 已断开";
		}
		websocket.onerror = function (error) {
			console.log("onerror--->" + error);
		}
	}

	function disconnect() {
		websocket.close();
	}

	function send(message) {
		if (!websocket) {
			return;
		}
		websocket.send(message);
	}

</script>

</html>